﻿/**
 *	\file		std_string.hpp
 *	\date		(2007-05-06 12:20:50)/(2015-02-20 17:19:42)
 *-----------------------------------------------------------------------------
 *	\version	1.0.25.35
 *	\author		Nick Shallery	(nicknide@gmail.com)
 *	\copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/

#if			!defined(__LOLIX__TOY__STD_STRING__NICK__K_IN_G__)
#define		__LOLIX__TOY__STD_STRING__NICK__K_IN_G__
//==============================================================================
//--------------------------------------------------------------------------

#if			!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)
	#include	"../lolix_cfg.h"
#endif	//	!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)

#if			!defined(__LOLIX__TOY__STD_VECTOR__NICK__K_IN_G__)
	#include	"./std_vector.hpp"
#endif	//	!defined(__LOLIX__TOY__STD_VECTOR__NICK__K_IN_G__)


namespace lolix{namespace toy{

template<class _Ty>
struct char_traits
{	// properties of a string or stream element
	typedef _Ty				value_type;
	typedef	_Ty*			pointer;
	typedef	const _Ty*		const_pointer;
	typedef	_Ty&			reference;
	typedef	const _Ty&		const_reference;

	typedef	size_type		size_type;
	typedef	difference_type	difference_type;

	static bool eq(const_reference _Left, const_reference _Right)
		{	// test for element equality
		return (_Left == _Right);
		}

	static bool lt(const_reference _Left, const_reference _Right)
		{	// test if _Left precedes _Right
		return (_Left < _Right);
		}

	static LOLIX_INLINE_CALL pointer next(pointer dec)
		{
		return ++dec;
		}

	static LOLIX_INLINE_CALL const_pointer next(const_pointer dec)
		{
		return ++dec;
		}

	static pointer prev(pointer dec)
		{
		return --dec;
		}

	static const_pointer prev(const_pointer dec)
		{
		return --dec;
		}

	static int compare(const_pointer in_l, const_pointer in_r, size_t in_cnt)
		{
		for (; 0 < in_cnt;--in_cnt, in_l = next(in_l), in_r = next(in_r) )
			if ( !eq(*in_r, *in_l) )
				return (lt(*in_r, *in_l) ? -1 : +1);
		return (0);
		}

	LOLIX_INLINE_CALL	size_type length(const_pointer in_pos)
		{
		size_t rtv;
		for ( rtv = 0; !eq(*in_pos, _tail_value); in_pos = next(in_pos) )
			++rtv;
		return rtv;
		}

	LOLIX_INLINE_CALL	const_reference tail(void)const
		{
		return _tail_value;
		}

	char_traits(void)
		: _tail_value()
		{}
private:
	value_type _tail_value;
};



template<typename _Ty, typename _CT = void, typename _Alc = lolix::allocator<_Ty> >
class basic_string
	: private vector<_Ty, _Alc>
{
	typedef	basic_string<_Ty, _CT, _Alc>	this_type;
	typedef	vector<_Ty, _Alc>	base_type;
	_CT _ct;
public:
	typedef				_Alc allocator_type;
	typedef typename	base_type::size_type		size_type;
	typedef typename	base_type::difference_type	difference_type;
	typedef typename	base_type::pointer			pointer;
	typedef typename	base_type::const_pointer	const_pointer;
	typedef typename	base_type::reference		reference;
	typedef typename	base_type::const_reference	const_reference;
	typedef typename	base_type::value_type		value_type;
	typedef	typename	base_type::const_iterator	const_iterator;
	typedef	typename	base_type::iterator			iterator;
	typedef	typename	base_type::reverse_iterator	reverse_iterator;
	typedef	typename	base_type::const_reverse_iterator	const_reverse_iterator;

	using base_type::get_allocator;
	static const size_type npos = size_type(0) - 1;

	class quick_compare
	{
	public:
		LOLIX_INLINE_CALL bool operator()(this_type const& l, this_type const& r)const
			{
			if ( l.length() < r.length() )
				return true;
			if ( l.length() > r.length() )
				return false;
			return l < r;
			}
	};

	LOLIX_INLINE_CALL	basic_string(void)
		: base_type(), _ct(), _len(0)
		{
		base_type::push_back(_ct.tail());
		}
	LOLIX_INLINE_CALL	basic_string(const value_type* in_src)
		: base_type(), _ct(), _len(0)
		{
		const size_type sz = _ct.length(in_src);
		this->__Assign(in_src/*, in_src + sz*/, sz);
		}
	LOLIX_INLINE_CALL	basic_string(const value_type* in_src, const allocator_type& in_alc)
		: base_type(in_alc), _ct(), _len(0)
		{
		assign(in_src);
		}

	LOLIX_INLINE_CALL	basic_string(const value_type* in_src, size_type in_cnt)
		: base_type(), _ct(), _len(0)
		{
		assign(in_src, in_src + in_cnt);
		}
	LOLIX_INLINE_CALL	basic_string(const value_type* in_src, size_type in_cnt, const allocator_type& in_alc)
		: base_type(in_alc), _ct(), _len(0)
		{
		assign(in_src, in_src + in_cnt);
		}

	template<typename _TIter>
	LOLIX_INLINE_CALL	basic_string(_TIter bg, _TIter ed)
		: base_type(), _ct(), _len(0)
		{
		assign(bg, ed);
		}

	template<typename _TIter>
	LOLIX_INLINE_CALL	basic_string(_TIter bg, _TIter ed, const allocator_type& in_alc)
		: base_type(in_alc), _ct(), _len(0)
		{
		assign(bg, ed);
		}

	LOLIX_INLINE_CALL	basic_string(const this_type& in_o)
		: base_type(in_o.get_allocator()), _ct(in_o._ct), _len(0)
		{
		this->__Assign(in_o.begin()/*, in_o.end()*/, in_o.length());
		}
	LOLIX_INLINE_CALL	basic_string(const this_type& in_o, size_type in_first_pos)
		: base_type(in_o.get_allocator()), _ct(), _len(0)
		{
		LOLIX_ASSERT(in_first_pos < in_o.length(), "invalid range");
		assign(in_o.begin() + in_first_pos, in_o.end());
		}
	LOLIX_INLINE_CALL	basic_string(const this_type& in_o, size_type in_first_pos, size_type in_cnt)
		: base_type(in_o.get_allocator()), _ct(), _len(0)
		{
		LOLIX_ASSERT(in_first_pos < in_o.length() && in_cnt + in_first_pos < in_o.length(), "invalid range");
		assign(in_o.begin() + in_first_pos, in_o.begin()+in_first_pos+in_cnt );
		}
	LOLIX_INLINE_CALL	basic_string(const this_type& in_o, size_type in_first_pos, size_type in_cnt, const allocator_type& in_alc)
		: base_type(in_alc), _ct(), _len(0)
		{
		LOLIX_ASSERT(in_first_pos < in_o.length() && in_cnt + in_first_pos < in_o.length(), "invalid range");
		assign(in_o.begin() + in_first_pos, in_o.begin()+in_first_pos+in_cnt );
		}

	LOLIX_INLINE_CALL	basic_string(size_type in_cnt, value_type in_value)
		: base_type(), _ct(), _len(0)
		{
		assign( in_cnt, in_value );
		}
	LOLIX_INLINE_CALL	basic_string(size_type in_cnt, value_type in_value, const allocator_type& in_alc)
		: base_type(in_alc), _ct(), _len(0)
		{
		assign( in_cnt, in_value );
		}

	LOLIX_INLINE_CALL	explicit basic_string(const allocator_type& in_alc )
		: base_type(in_alc), _ct(), _len(0)
		{
		base_type::push_back(_ct.tail());
		}
#if			LOLIX_CFG__SUPPORT_CPP_0X
	LOLIX_INLINE_CALL	basic_string(basic_string&& o)
		: base_type(forward<base_type>(o))
		, _ct(forward<_CT>(o._ct))
		, _len(o._len)
		{
		}
#endif	//	LOLIX_CFG__SUPPORT_CPP_0X

	LOLIX_INLINE_CALL	this_type&	append(const value_type* in_pvalue)
		{
		const size_type cnt = _ct.length(in_pvalue);
		return this->__Append(in_pvalue/*, in_pvalue+cnt*/, cnt);
		}
	LOLIX_INLINE_CALL	this_type&	append(const value_type* in_pvalue,size_type in_cnt)
		{
		return this->append(in_pvalue, in_pvalue+in_cnt);
		}
	LOLIX_INLINE_CALL	this_type&	append(const this_type&	in_o,size_type in_begin, size_type in_cnt)
		{
		LOLIX_ASSERT(in_o.length() > in_begin, "out of range");
		if ( in_cnt + in_begin > in_o.length() )
			in_cnt = in_o.length - in_begin;
		return this->__Append(in_o.begin()+in_begin, in_cnt);
		}
	LOLIX_INLINE_CALL	this_type&	append(const this_type&	in_o)
		{
		return this->__Append(in_o.begin(), in_o.length());
		}
	LOLIX_INLINE_CALL	this_type&	append(size_type in_cnt, value_type in_value)
		{
		return this->__Append( make_value_iterator(in_value, 0), in_cnt );
		}
	LOLIX_INLINE_CALL	this_type&	append(value_type in_val)
		{ return this->append(1, in_val); }
	template<class _InIt>
	LOLIX_INLINE_CALL	this_type&	append(_InIt in_l, _InIt in_r)
		{
		_InIt in_begin = in_l;
		size_type i = 0;
		for ( ; in_l != in_r && *in_l != _ct.tail(); ++in_l, ++i )
			;
		return this->__Append(in_begin, i);
		}


	LOLIX_INLINE_CALL	this_type&	assign(const value_type* in_ptr)
		{
		size_type st = _ct.length(in_ptr);
		return this->__Assign(in_ptr, st);
		}
	LOLIX_INLINE_CALL	this_type&	assign(const value_type* in_ptr, size_type cnt)
		{
		return this->assign(in_ptr, in_ptr + cnt);
		}
	LOLIX_INLINE_CALL	this_type&	assign(const this_type&	in_ot, size_type off, size_type cnt)
		{
		LOLIX_ASSERT(in_ot.size() > off && in_ot.size() >= off + cnt, L"OUT OF RANGE ERROR");
		return this->__Assign(in_ot.begin()+off, cnt);
		}
	LOLIX_INLINE_CALL	this_type&	assign(const this_type&	in_o)
		{
		return (*this) = in_o;
		}
	LOLIX_INLINE_CALL	this_type&	assign(size_type cnt, const_reference val)
		{
		value_iterator<typename remove_reference<const_reference>::type, const_reference, const_reference> it_begin(val);
		return this->__Assign(it_begin, cnt);
		}
	template<class _InIt>
	LOLIX_INLINE_CALL	this_type&	assign(_InIt in_l, _InIt in_r)
		{
		size_type st_len = 0;
		_InIt in_begin = in_l;
		for ( ; in_l != in_r && *in_l != _ct.tail(); ++in_l, ++st_len )
			;
		return this->__Assign(in_begin, st_len);
		}

	LOLIX_INLINE_CALL const_reference	front(void)const
		{
		LOLIX_ASSERT(!this->empty(), L"访问越界：针对空的字符串使用 back 访问限定符");
		return *this->begin();
		}

	LOLIX_INLINE_CALL reference	front(void)
		{
		LOLIX_ASSERT(!this->empty(), L"访问越界：针对空的字符串使用 back 访问限定符");
		return *this->begin();
		}

	LOLIX_INLINE_CALL const_reference	back(void)const
		{
		LOLIX_ASSERT(!this->empty(), L"访问越界：针对空的字符串使用 back 访问限定符");
		return *--end();
		}
	LOLIX_INLINE_CALL reference	back(void)
		{
		LOLIX_ASSERT(!this->empty(), L"访问越界：针对空的字符串使用 back 访问限定符");
		return *--end();
		}

	using base_type::begin;

	LOLIX_INLINE_CALL iterator erase(iterator iter)
		{
		LOLIX_ASSERT(iter != end(), L"erase 迭代器末尾, 错误!");
		--_len;
		return base_type::erase(iter);
		}

	LOLIX_INLINE_CALL void erase(iterator start, iterator last)
		{
		this_type::erase(start - begin(), last - start);
		}

	LOLIX_INLINE_CALL void erase(size_type start_pos, size_type del_len)
		{
		LOLIX_ASSERT(start_pos + del_len <= _len, L"删除的时候越界");
		base_type::erase(this_type::begin() + start_pos, this_type::begin() + start_pos + del_len);
		_len -= del_len;
		}

	LOLIX_INLINE_CALL	const_pointer		c_str(void)const
		{
		return _len?&*begin():&_ct.tail();
		}
	LOLIX_INLINE_CALL	size_type		capacity(void)const
		{
		return base_type::capacity() - 1;
		}
	LOLIX_INLINE_CALL	void		clear(void)
		{
		this_type::resize(0);
		}
	LOLIX_INLINE_CALL	bool		empty(void)const
		{
		return _len?false:true;
		}
	LOLIX_INLINE_CALL	iterator	end(void)
		{
		return begin() + _len;
		}
	LOLIX_INLINE_CALL	const_iterator	end(void)const
		{
		return begin() + _len;
		}
	LOLIX_INLINE_CALL	size_type find_last_of(const value_type& ch, size_type lastpos = npos)const
		{
		if ( empty() )
			return npos;

		if ( lastpos == npos )
			lastpos = length();

		size_type curpos = lastpos - 1;
		do
			{
			if ( _ct.eq(this->operator[](curpos), ch) )
				return curpos;
			}
		while(curpos--);
		return npos;
		}
	LOLIX_INLINE_CALL	void insert(iterator in_where, const this_type& other)
		{
		base_type::insert(in_where, other.begin(), other.end());
		_len += other._len;
		}
	LOLIX_INLINE_CALL	void insert(iterator in_where, size_type cnt, const_reference val)
		{
		base_type::insert(in_where, cnt, val);
		_len += cnt;
		}
	LOLIX_INLINE_CALL	iterator	insert(iterator in_where, const_reference val)
		{
		iterator iter(base_type::insert(in_where, val));
		++_len;
		return iter;
		}
	template<typename _Ti>
	LOLIX_INLINE_CALL	void	insert(iterator in_where, _Ti begin_iter, _Ti end_iter)
		{
		const size_type old_size = base_type::size();
		base_type::insert(in_where, begin_iter, end_iter);
		_len += base_type::size() - old_size;
		}

	LOLIX_INLINE_CALL	size_type	length(void)const
		{
		return _len;
		}

	LOLIX_INLINE_CALL void	pop_back(void)
		{
		LOLIX_ASSERT(!this->empty(), L"针对空的字符串进行 pop_back 操作");
		--_len;
		}

	LOLIX_INLINE_CALL void	push_back(value_type v)
		{
		insert(end(), v);
		}


	LOLIX_INLINE_CALL void	resize(size_type new_size)
		{
		base_type::resize(new_size);
		base_type::push_back(_ct.tail());
		_len = new_size;
		}

	LOLIX_INLINE_CALL void	resize(size_type new_size, value_type v)
		{
		base_type::resize(_len);
		base_type::resize(new_size, v);
		base_type::push_back(_ct.tail());
		_len = new_size;
		}

	LOLIX_INLINE_CALL void reserve(size_type cap)
		{
		base_type::reserve(cap+1);
		}

	LOLIX_INLINE_CALL	this_type&	operator = (const_pointer other)
		{
		return this->assign(other);
		}

	LOLIX_INLINE_CALL	this_type&	operator = (const_reference other)
		{
		return this->assign(1, other);
		}
#if			LOLIX_CFG__SUPPORT_CPP_0X
	LOLIX_INLINE_CALL	this_type& operator = (this_type const& o)
		{
		base_type::operator = (o);
		_ct = o._ct;
		_len = o._len;
		return *this;
		}
	LOLIX_INLINE_CALL	this_type& operator = (this_type&& o)
		{
		base_type::operator = (forward<base_type>(o));
		_ct = forward<_CT>(o._ct);
		_len = o._len;
		return *this;
		}
#endif	//	LOLIX_CFG__SUPPORT_CPP_0X


	LOLIX_INLINE_CALL	bool operator < (const this_type& o)const
		{
		size_type i = 0;
		do
			if ( _ct.lt((*this)[i], o[i]) )
				return true;
			else if ( _ct.lt(o[i], (*this)[i]) )
				return false;
		while((*this)[i++]);
		return false;
		}

	LOLIX_INLINE_CALL	bool operator > (const this_type& o)const
		{
		size_type i = 0;
		do
			if ( _ct.lt((*this)[i], o[i]) )
				return false;
			else if ( _ct.lt(o[i], (*this)[i]) )
				return true;
		while((*this)[i++]);
		return false;
		}

	LOLIX_INLINE_CALL	this_type&	operator += (typename type::type_def<value_type>::const_value_type val)
		{
		insert(end(), val);
		return *this;
		}

	LOLIX_INLINE_CALL	this_type&	operator += (const value_type* val)
		{
		const size_type c_len = _ct.length(val);
		return __Append(val, c_len);
		}

	LOLIX_INLINE_CALL	this_type&	operator += (const this_type& o)
		{
		return __Append(o.c_str(), o._len);
		}


	template<typename _To>
	LOLIX_INLINE_CALL	this_type	operator + (const _To& val)const
		{
			this_type tmp(*this);
			tmp += val;
			return tmp;
		}

	LOLIX_INLINE_CALL	bool		operator == (const this_type& o)const
		{
		if ( _len != o._len )
			return false;
		for ( size_type i = 0; i != _len; ++i )
			if ( (*this)[i] != o[i] )
				return false;
		return true;
		//return memcmp(this->c_str(), o.c_str(), _len) == 0;
		}

	LOLIX_INLINE_CALL	bool		operator == (const_pointer o)const
		{
		for ( size_type i = 0; i != _len; ++i )
			if ( (*this)[i] != o[i] )
				return false;
		return true;
		}


	template <typename _To>
	LOLIX_INLINE_CALL	bool		operator != (_To& o)const
		{
		return	!((*this) == o);
		}

	LOLIX_INLINE_CALL	reference	operator [](size_type i)
		{
		return base_type::operator[](i);
		}


	LOLIX_INLINE_CALL	const_reference	operator [](size_type i)const
		{
		return base_type::operator[](i);
		}

	LOLIX_INLINE_CALL	void		swap(this_type& o)
		{
		base_type::swap(o);
		size_type tmp_len = o._len;
		o._len = _len;
		_len = tmp_len;
		}

	LOLIX_INLINE_CALL	size_type	size(void)const
		{
		return _len;
		}

private:
	template<typename IpIt>
	LOLIX_INLINE_CALL	this_type&	__Assign(IpIt in_l, size_type new_len)
		{
		this_type::clear();
		return this->__Append(in_l, new_len);
		}

	template<typename IpIt>
	LOLIX_INLINE_CALL	this_type&	__Append(IpIt in_l, size_type new_len)
		{
		base_type::__Insert_by_number(begin()+_len, in_l, new_len);
		_len += new_len;
		if ( base_type::size() == _len )
			base_type::push_back(_ct.tail());
		return *this;
		}

	size_type	_len;
};


template<typename _Ty, typename _Alc>
class basic_string<_Ty, void, _Alc>
	: public basic_string<_Ty, char_traits<_Ty>, _Alc>
{
	typedef	basic_string<_Ty, void, _Alc>				this_type;
	typedef	basic_string<_Ty, char_traits<_Ty>, _Alc>	base_type;
public:
	typedef typename	base_type::allocator_type	allocator_type;
	typedef typename	base_type::size_type		size_type;
	typedef typename	base_type::difference_type	difference_type;
	typedef typename	base_type::pointer			pointer;
	typedef typename	base_type::const_pointer	const_pointer;
	typedef typename	base_type::reference		reference;
	typedef typename	base_type::const_reference	const_reference;
	typedef typename	base_type::value_type		value_type;
	typedef	typename	base_type::const_iterator	const_iterator;
	typedef	typename	base_type::iterator			iterator;
	typedef	typename	base_type::reverse_iterator	reverse_iterator;
	typedef	typename	base_type::const_reverse_iterator	const_reverse_iterator;

#define		__REDEF_CTOR__0()					LOLIX_INLINE_CALL	basic_string(void): base_type(){}
#define		__REDEF_CTOR__1(p0)					LOLIX_INLINE_CALL	basic_string(p0 _p0): base_type(_p0){}
#define		__REDEF_CTOR__2(p0, p1)				LOLIX_INLINE_CALL	basic_string(p0 _p0, p1 _p1): base_type(_p0, _p1){}
#define		__REDEF_CTOR__3(p0, p1, p2)			LOLIX_INLINE_CALL	basic_string(p0 _p0, p1 _p1, p2 _p2): base_type(_p0, _p1, _p2){}
#define		__REDEF_CTOR__4(p0, p1, p2, p3)		LOLIX_INLINE_CALL	basic_string(p0 _p0, p1 _p1, p2 _p2, p3 _p3): base_type(_p0, _p1, _p2, _p3){}
#define		__REDEF_CTOR__EXPLICIT__1(p0)		LOLIX_INLINE_CALL	explicit basic_string(p0 _p1): base_type(_p1){}

	__REDEF_CTOR__0()
	__REDEF_CTOR__1(const this_type&)
	__REDEF_CTOR__1(const const_pointer);
	__REDEF_CTOR__2(const const_pointer, const allocator_type&)
	__REDEF_CTOR__2(const value_type*, size_type)
	__REDEF_CTOR__3(const value_type*, size_type, const allocator_type&)

	__REDEF_CTOR__1(const base_type& )
	__REDEF_CTOR__2(const base_type& , size_type)
	__REDEF_CTOR__3(const base_type& , size_type, size_type)
	__REDEF_CTOR__4(const base_type& , size_type, size_type, const allocator_type&)
	__REDEF_CTOR__2(size_type , value_type)
	__REDEF_CTOR__3(size_type , value_type, const allocator_type&)
	__REDEF_CTOR__EXPLICIT__1(const allocator_type&)

	template<typename _TIter>
	__REDEF_CTOR__2(_TIter, _TIter)
	template<typename _TIter>
	__REDEF_CTOR__3(_TIter, _TIter, const allocator_type&)


#if			LOLIX_CFG__SUPPORT_CPP_0X
	LOLIX_INLINE_CALL basic_string(basic_string&& o)
		: base_type(forward<base_type>(o))
		{
		}
#endif	//	LOLIX_CFG__SUPPORT_CPP_0X

#undef		__REDEF_CTOR__0
#undef		__REDEF_CTOR__1
#undef		__REDEF_CTOR__2
#undef		__REDEF_CTOR__3
#undef		__REDEF_CTOR__4
#undef		__REDEF_CTOR__EXPLICIT__0

	template <typename _Tp>
	LOLIX_INLINE_CALL	this_type&	operator = (_Tp const& other)
		{
		base_type::operator = (other);
		return *this;
		}

#if			LOLIX_CFG__SUPPORT_CPP_0X
	LOLIX_INLINE_CALL	this_type& operator = (this_type const& o)
		{
		base_type::operator = (o);
		return *this;
		}
	LOLIX_INLINE_CALL	this_type& operator = (this_type&& o)
		{
		base_type::operator = (forward<base_type>(o));
		return *this;
		}
#endif	//	LOLIX_CFG__SUPPORT_CPP_0X
};

typedef	basic_string<char> string;
typedef	basic_string<lx_u8> utf8_string;
typedef	basic_string<lx_wchar> wstring;

LOLIX_INLINE_CALL utf8_string& assign(utf8_string& l, wstring const& r)
{
	l.clear();
	l.reserve(r.length());
	for ( wstring::const_iterator iter = r.begin(); iter != r.end(); ++iter )
	{
		lx_u32 val;// = *iter;
		if ( sizeof(*iter) == 2 )
		{
			const lx_wchar vh = *iter;
			if ( 0xd800 <= vh && vh <= 0xdfff )
			{
				++iter;
				if ( iter == r.end() )
					break;
				const lx_wchar vl = *iter;
				val = ((vh - 0xd800) << 10) + (vl - 0xdc00);
				val += 0x10000;
			}
			else
			{
				val = *iter;
			}
		}
		else
		{
			val = *iter;
		}

		if ( (lx_u32)val <= 0x7f )
		{
			l.push_back((utf8_string::value_type)val);
			continue;
		}
		if ( (lx_u32)val <= 0x03ff )
		{
			l.push_back((utf8_string::value_type)(val>>6)+0xc0);
			l.push_back((utf8_string::value_type)(val&0x3f) + 0x80);
			continue;
		}
		if ( (lx_u32)val <= 0xffff )
		{
			l.push_back((utf8_string::value_type)(val>>12)+0xe0);
			l.push_back((utf8_string::value_type)(((val>>6)&0x3f)+0x80));
			l.push_back((utf8_string::value_type)(val&0x3f)+0x80);
			continue;
		}
		if ( (lx_u32)val <= 0x1fffff )
		{
			l.push_back((utf8_string::value_type)(val>>18)+0xf0);
			l.push_back((utf8_string::value_type)(((val>>12)&0x3f)+0x80));
			l.push_back((utf8_string::value_type)(((val>>6)&0x3f)+0x80));
			l.push_back((utf8_string::value_type)(val&0x3f)+0x80);
			continue;
		}
		if ( (lx_u32)val <= 0x03ffffff )
		{
			l.push_back((utf8_string::value_type)(val>>24)+0xf8);
			l.push_back((utf8_string::value_type)(((val>>18)&0x3f)+0x80));
			l.push_back((utf8_string::value_type)(((val>>12)&0x3f)+0x80));
			l.push_back((utf8_string::value_type)(((val>>6)&0x3f)+0x80));
			l.push_back((utf8_string::value_type)(val&0x3f)+0x80);
			continue;
		}

		l.push_back((utf8_string::value_type)(val>>30)+0xfc);
		l.push_back((utf8_string::value_type)(((val>>24)&0x3f)+0x80));
		l.push_back((utf8_string::value_type)(((val>>18)&0x3f)+0x80));
		l.push_back((utf8_string::value_type)(((val>>12)&0x3f)+0x80));
		l.push_back((utf8_string::value_type)(((val>>6)&0x3f)+0x80));
		l.push_back((utf8_string::value_type)(val&0x3f)+0x80);
	}
	return l;
}


LOLIX_INLINE_CALL wstring& assign(wstring& l, utf8_string const& r)
{
	l.clear();
	utf8_string::const_iterator iter = r.begin();
	while ( iter != r.end() )
	{
		lx_char rv = *iter;
		if ( (rv & 0x80) == 0x00 )
		{
			l.push_back(rv);
			++iter;
			continue;
		}

		size_type less;
		lx_u32 val;
		if ( (rv & 0xe0) == 0xc0 )	//	110x xxxx
		{
			val = (rv & 0x1f) << 6;
			less = 1;
		}
		else if ( (rv & 0xf0) == 0xe0 )	//	1110 xxxx
		{
			val = (rv & 0x0f) << 12;
			less = 2;
		}
		else if ( (rv & 0xf8) == 0xf0 )	//	1111 0xxx
		{
			val = (rv & 0x07) << 18;
			less = 3;
		}
		else if ( (rv & 0xfc) == 0xf8 )	//	1111 10xx
		{
			val = (rv & 0x03) << 24;
			less = 4;
		}
		else if ( (rv & 0xfe) == 0xfc )	//	1111 110x
		{
			val = (rv & 0x01) << 30;
			less = 5;
		}

		for ( ++iter; iter != r.end() && less; --less, ++iter )
		{
			rv = *iter;
			val += ((rv & 0x3f) << ((less - 1)* 6));
		}

		if ( less )
		{
			LOLIX_ASSERT(0, L"Invalid Utf8-String");
			return l;	//	error here.
		}

		if ( sizeof(l.front()) == 4 )
		{
			l.push_back(val);
		}
		else if ( sizeof(l.front()) == 2 && val < 0xd800 )
		{
			l.push_back((lolix::lx_wchar)val);
		}
		else if ( val < 0x110000 )
		{
			remove_reference<decltype(l)>::type::value_type vl, vh;
			val -= 0x10000;
			vh = (val >> 10) & 0x03ff;
			vh += 0xD800;
			vl = (val & 0x03ff);
			vl += 0xDC00;
			l.push_back(vh);
			l.push_back(vl);
		}
		else
		{
			LOLIX_ASSERT(0, L"Invalid Utf8-String");
			return l;	//	error here.
		}
	}
	return l;
}

}}

namespace lolix{
	template<typename _Ty, typename _CT, typename _Alc>
	LOLIX_INLINE_CALL void swap(toy::basic_string<_Ty, _CT, _Alc>& tl, toy::basic_string<_Ty, _CT, _Alc>& tr)
	{ tl.swap(tr); }
	template<typename _Ty, typename _CT, typename _Alc>
	LOLIX_INLINE_CALL void discard_copy(toy::basic_string<_Ty, _CT, _Alc>& tl, toy::basic_string<_Ty, _CT, _Alc>& tr)
	{ tl.swap(tr); }
}

//--------------------------------------------------------------------------
//==============================================================================
#endif	//	!defined(__LOLIX__TOY__STD_STRING__NICK__K_IN_G__)
